package org.cupk2.wdap.convertor.utils;

import lombok.Synchronized;
import org.cupk2.base.domain.CupkUserContextLoader;
import org.cupk2.base.event.enums.F2EActionT;
import org.cupk2.base.event.enums.F2EObjectT;
import org.cupk2.base.event.face.Cupk2Events;
import org.cupk2.files.domain.ResourceFile;
import org.cupk2.tools.files.Cupk2ProcessState;
import org.cupk2.wdap.domain.WdapFlow;
import org.cupk2.wdap.domain.WdapTask;
import org.cupk2.wdap.service.WdapExtendFileServiceInter;
import org.cupk2.wdap.service.WdapFlowServiceInter;
import org.cupk2.wdap.service.WdapTaskServiceInter;
import org.cupk2.wdap.service.impl.WdapFlowServiceImpl;
import org.cupk2.wdap.utils.WdapJsonLogs;
import org.cupk2.wdap.utils.WdapTaskStateEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 用来执行转换流程得类
 */
@Component
public class WdapFlowRunner {
    @Autowired
    private WdapTaskServiceInter wdapTaskServiceImpl;
    @Autowired
    private WdapFlowServiceInter wdapFlowServiceImpl;
    @Autowired
    private WdapExtendFileServiceInter wdapExtendFileServiceImpl;

    /**
     * 当前是否有任务在转换
     */
    private static boolean isTaskRunner = false;

    @Synchronized
    public void startRunTasks() {
        if (isTaskRunner == false) {
            isTaskRunner = true;
            new Thread(() -> {
                try {
                    Cupk2ProcessState.sleep(3000);
                    List<WdapTask> tasks = wdapTaskServiceImpl.getWaitTask(1000);
                    for (WdapTask taskNode : tasks) {
                        try {
                            String taskId = taskNode.getId();
                            WdapTask task = wdapTaskServiceImpl.getWdapTaskById(taskId);
                            List<WdapFlow> flows = wdapTaskServiceImpl.findTaskFlowsAndUpdateState(taskId);
                            ResourceFile rfile = wdapTaskServiceImpl.getResourceFileIdByTaskId(taskId);
                            run(flows, rfile, task);
                        } catch (Exception e) {
                            taskNode.setPstate(WdapTaskStateEnum.ERROR.code);
                            wdapTaskServiceImpl.updateState(WdapJsonLogs.addLog(taskNode, WdapJsonLogs.LogType.ERROR, e.getMessage()));
                        }
                    }
                } finally {
                    isTaskRunner = false;
                }
            }).start();
        }
    }

    /**
     * 同步执行[指定的]转换流程
     *
     * @param flows
     * @param rfile
     * @param task
     */
    private void run(List<WdapFlow> flows, ResourceFile rfile, WdapTask task) {
        try {

            wdapExtendFileServiceImpl.clearExtendFileByTask(task.getId());
            task.setLogjson(WdapJsonLogs.getInstance().toJson());
            task.setPstate("1");
            for (WdapFlow flow : flows) {
                wdapTaskServiceImpl.updateState(WdapJsonLogs.addLog(task, WdapJsonLogs.LogType.INFO, "开始流程-" + flow.getName()));

                int runNodeNum = 0;

                String nodeId = WdapFlowServiceImpl.START_NODE_ID;
                Map<String, Object> context = new HashMap<>();
                while (!nodeId.equals("END")) {

                    runNodeNum++;
                    if (runNodeNum > 10) {
                        throw new RuntimeException("流程执行超长：" + runNodeNum);
                    }
                    nodeId = wdapFlowServiceImpl.runFlow(flow.getId(), task, nodeId, rfile, context);
                }
                wdapTaskServiceImpl.updateState(WdapJsonLogs.addLog(task, WdapJsonLogs.LogType.INFO, "完成流程-" + flow.getName()));
            }
            task.setPstate(WdapTaskStateEnum.COMPLETE.code);
            wdapTaskServiceImpl.updateState(WdapJsonLogs.addLog(task, WdapJsonLogs.LogType.INFO, "全部转换完成"));
            Cupk2Events.emit(F2EObjectT.FILE, task.getFileid(), F2EActionT.EXTEND_FILE, CupkUserContextLoader.getCurrentUser());
        } catch (Exception e) {
            task.setPstate(WdapTaskStateEnum.ERROR.code);
            wdapTaskServiceImpl.updateState(WdapJsonLogs.addLog(task, WdapJsonLogs.LogType.ERROR, e.getMessage()));
        }
    }
}
